package com.cardone.common.function;

import com.cardone.common.util.*;
import com.cardone.context.*;
import com.cardone.context.function.*;
import lombok.extern.slf4j.*;
import org.apache.commons.compress.archivers.zip.*;
import org.apache.commons.io.*;
import org.apache.commons.lang.StringUtils;

import java.io.*;

/**
 * ContextHolder.getBean(UnZipFileFunction.class).execution(filename, password);
 *
 * @author yaohaitao
 */
@Slf4j
public class UnZipFileFunction implements Execution2Function<String, String, String> {
    @Override
    public String execution(final String zipFilename, final String password) {
        final String fileFullPath = FilenameUtils.getFullPath(zipFilename);

        final String fileBaseName = FilenameUtils.getBaseName(zipFilename);

        final String fileExtension = FilenameUtils.getExtension(zipFilename);

        String filename = null;

        final String tempFilename = StringUtils.join(new String[]{fileFullPath, fileBaseName, "_temp.", fileExtension});

        final int bufferLen = 1024 * 1024;

        final File zipFile = new File(tempFilename);

        final File outDir = new File(fileFullPath);

        try {
            CipherUtils.decrypt(zipFilename, tempFilename, password);
        } catch (final Exception e) {
            throw new DictionaryException("解密失败", e);
        }

        try (FileInputStream fis = new FileInputStream(zipFile)) {
            try (BufferedInputStream bis = new BufferedInputStream(fis, bufferLen)) {
                try (ZipArchiveInputStream is = new ZipArchiveInputStream(bis)) {
                    ZipArchiveEntry entry;

                    while ((entry = is.getNextZipEntry()) != null) {
                        if (entry.isDirectory()) {
                            final File directory = new File(outDir, entry.getName());

                            if (!directory.exists()) {
                                directory.mkdirs();
                            }

                            break;
                        }

                        try (FileOutputStream fos = new FileOutputStream(new File(outDir, entry.getName()))) {
                            try (BufferedOutputStream bos = new BufferedOutputStream(fos, bufferLen)) {
                                IOUtils.copy(is, bos);
                            }
                        }

                        filename = StringUtils.join(new String[]{fileFullPath, entry.getName()});
                    }
                }
            }
        } catch (java.io.IOException e) {
            throw new DictionaryException(e.getMessage(), e);
        } finally {
            FileUtils.deleteQuietly(new File(tempFilename));
        }

        return filename;
    }
}
